package soar.test.misc;

import java.util.Arrays;
import java.util.Properties;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class App
{
    private static final String __CLASS__ = App.class.getName();

    public static void main(String[] args)
    {
        new App().run();
    }

    private void run()
    {
        final String __METHOD__ = "run";

        try
        {
            String split = "========================================";

            name();
            System.out.println(split);

            properties();
            System.out.println(split);

            runtime();
            System.out.println(split);

            print();
            System.out.println(split);

            enumerate();
            System.out.println(split);

            array();
            System.out.println(split);

            map();
            System.out.println(split);

            cls();
            System.out.println(split);

            random();
            System.out.println(split);

            uuid();
            System.out.println(split);

            operator();
            System.out.println(split);

            string();
            System.out.println(split);

            integer();
            System.out.println(split);

            charset();
            System.out.println(split);

            singleton();
            System.out.println(split);

            static_member();
            System.out.println(split);

            varargs();
            System.out.println(split);
        }
        catch (Exception e)
        {
            System.err.println(
                    String.format("%s.%s: %s", __CLASS__, __METHOD__, e));
        }
    }

    enum Color
    {
        RED, BLUE, GREEN;
    }

    enum ColorCustom
    {
        RED("红"), BLUE("蓝"), GREEN("绿");

        private String zh;

        private ColorCustom(String zh)
        {
            this.zh = zh;
        }

        public String getZh()
        {
            return zh;
        }

        public void setZh(String zh)
        {
            this.zh = zh;
        }

        @Override
        public String toString()
        {
            return name().toLowerCase();
        }
    }

    class ColorC
    {
        public static final int RED = 1;
        public static final int BLUE = 2;
        public static final int GREEN = 3;
    }

    static class Unit
    {
        public String s;
    }

    private void name()
    {
        System.out.println(
                String.format("this name: %s", this.getClass().getName()));
        System.out.println(String.format("this simple name: %s",
                this.getClass().getSimpleName()));
        System.out
                .println(String.format("class name: %s", App.class.getName()));
        System.out.println(String.format("class simple name: %s",
                App.class.getSimpleName()));
        System.out.println(String.format("package name: %s",
                App.class.getPackage().getName()));
        System.out.println(String.format("package toString: %s",
                App.class.getPackage().toString()));
    }

    private void properties()
    {
        Properties props = System.getProperties();
        Iterator<Object> it = props.keySet().iterator();
        while (it.hasNext())
        {
            String key = (String) it.next();
            String val = props.getProperty(key);
            System.out.println(String.format("%s: %s", key, val));
        }
    }

    private void runtime()
    {
        Runtime runtime = Runtime.getRuntime();
        System.out.println(String.format("availableProcessors: %d",
                runtime.availableProcessors()));
        System.out
                .println(String.format("maxMemory: %,d", runtime.maxMemory()));
        System.out.println(
                String.format("totalMemory: %,d", runtime.totalMemory()));
        System.out.println(
                String.format("freeMemory: %,d", runtime.freeMemory()));
    }

    private void print()
    {
        String s = "19";
        boolean b = Integer.parseInt(s) > 100 ? true : false;
        System.out.println(s + " > 100 : " + b);
        System.out.println(String.format("boolean: %s", true));
    }

    private void enumerate()
    {
        Color c = Color.BLUE;
        System.out.println("Color: " + c);
        System.out.println("ColorC: " + ColorC.RED);
        System.out
                .println(String.format("Color: %s %d", c.name(), c.ordinal()));
        System.out.println(Arrays.asList(Color.values()).stream()
                .map(x -> x.name() + ":" + x.ordinal())
                .collect(Collectors.joining("|")));
        ColorCustom cc = ColorCustom.RED;
        System.out.println(String.format("ColorCustom: %s %s %d %s", cc,
                cc.name(), cc.ordinal(), cc.getZh()));
    }

    private void array()
    {
        String split = "------------------------------";

        System.out.println("array()");
        System.out.println(split);

        String[] sarr = { "A", "B", "C" };
        for (String s : sarr)
        {
            System.out.println(s);
        }

        System.out.println(split);

        class A
        {
            int i;
            String s;
        }
        class ANode
        {
            Object lock;
            A a;
        }
        ANode[] arr = new ANode[1000000];
        for (int i = 0; i < arr.length; ++i)
        {
            arr[i] = new ANode();
            arr[i].lock = new Object();
        }
        for (int i = 0; i < arr.length; ++i)
        {
            synchronized (arr[i].lock)
            {
                if (arr[i].a != null)
                {
                    System.out.println("impossible");
                }
            }
        }
        System.out.println("load done");

        System.out.println(split);

        List<String> l = new ArrayList<String>();
        l.add("hello");
        l.add("world");
        System.out.println(l.get(1));
        for (String s : l)
        {
            System.out.println(s);
        }

        System.out.println(split);

        ArrayList<String> slist = new ArrayList<String>();
        slist.add("A");
        slist.add("B");
        slist.add("C");
        String s = "ABC";
        String b = s.substring(1, 2);
        if (slist.contains(b))
        {
            System.out.println("slist contains B");
        }

        System.out.println(split);

        System.out.println("比较List");
        List<String> list0 = Arrays.asList(new String[0]);
        System.out.println(String.format("empty: %s", list0.toString()));
        String[] a1 = { "A", "B", "C" };
        List<String> list1 = Arrays.asList(a1);
        list1.sort(String::compareTo);
        String[] a2 = { "C", "A", "B" };
        List<String> list2 = Arrays.asList(a2);
        list2.sort(String::compareTo);
        String list1_s = list1.toString();
        String list1_j = list1.stream().collect(Collectors.joining());
        String list2_s = list2.toString();
        String list2_j = list2.stream().collect(Collectors.joining());
        if (list1_s.equals(list2_s))
        {
            System.out.println(String.format("%s == %s", list1_s, list2_s));
        }
        if (list1_j.equals(list2_j))
        {
            System.out.println(String.format("%s == %s", list1_j, list2_j));
        }

        System.out.println(split);

        HashSet<String> hs = new HashSet<String>();
        hs.add("a");
        hs.add("a");
        hs.add("b");
        hs.add("c");
        System.out.println(hs.toString());

        System.out.println(split);

        System.out.println("合并数组");
        System.out.println();

        String[] arr1 = { "A", "B", "C" };
        System.out.println("arr1");
        Stream.of(arr1).forEach(System.out::println);
        System.out.println();
        String[] arr2 = { "X", "Y", "Z" };
        System.out.println("arr2");
        Stream.of(arr2).forEach(System.out::println);
        System.out.println();
        String[] arr_merge = new String[arr1.length + arr2.length];
        System.arraycopy(arr1, 0, arr_merge, 0, arr1.length);
        System.arraycopy(arr2, 0, arr_merge, arr1.length, arr2.length);
        System.out.println("arr_merge");
        Stream.of(arr_merge).forEach(System.out::println);

        System.out.println(split);

        System.out.println("遍历数组");
        System.out.println();

        for (String[] i : new String[][] { { "1", "2", "3" },
                { "A", "B", "C", "D" } })
        {
            for (String j : i)
            {
                System.out.print(j + " ");
            }
            System.out.println();
        }

        for (List<String> i : Arrays.asList(Arrays.asList("1", "2", "3"),
                Arrays.asList("A", "B", "C", "D")))
        {
            for (String j : i)
            {
                System.out.print(j + " ");
            }
            System.out.println();
        }

        System.out.println(split);

        System.out.println("分拆列表（3个一组）");
        System.out.println();
        List<String> list = Arrays.asList("一", "二", "三", "四", "五", "六", "七");
        List<List<String>> list_group = splitList(list, 3);
        list_group.forEach(x -> {
            System.out.println(x.stream().collect(Collectors.joining(", ")));
        });

        System.out.println(split);

        String[] inputs = { ".一", "abc", "ABC", "一二三", "/abc/", "00.00" };
        for (String input : inputs)
        {
            char ch = input.charAt(0);
            if (Character.isDigit(ch))
            {
                System.out.println(String.format("%s: digit", input));
            }
            else if (Character.isUpperCase(ch))
            {
                System.out.println(String.format("%s: uppercase", input));
            }
            else if (Character.isLowerCase(ch))
            {
                System.out.println(String.format("%s: lowercase", input));
            }
            else if (is_utf8(ch))
            {
                System.out.println(String.format("%s: utf8", input));
            }
            else
            {
                System.out.println(String.format("%s: invalid", input));
            }
        }
    }

    private <T> List<List<T>> splitList(List<T> list, int size)
    {
        List<List<T>> group = new ArrayList<>();
        for (int from_index = 0; from_index < list.size(); from_index += size)
        {
            int to_index = from_index + size;
            if (to_index > list.size())
                to_index = list.size();
            group.add(list.subList(from_index, to_index));
        }
        return group;
    }

    private void map()
    {
        System.out.println("map()");
        String split = "------------------------------";
        System.out.println(split);

        @SuppressWarnings("hiding")
        class Unit
        {
            int id;
            String s;
        }
        HashMap<Integer, Unit> m = new HashMap<>();
        Unit unit;
        unit = new Unit();
        unit.id = 1;
        unit.s = "hello";
        m.put(unit.id, unit);
        unit = new Unit();
        unit.id = 3;
        unit.s = "world";
        m.put(unit.id, unit);
        System.out.println(m.get(1).s);

        for (Unit u : m.values())
        {
            if (u.id == 1)
                u.s = "HELLO";
            // if(u.id == 1) //不允许,java.util.ConcurrentModificationException
            // m.remove(u.id);
        }
        for (Unit u : m.values())
        {
            System.out.println(u.id + ":" + u.s);
        }

        Iterator<Map.Entry<Integer, Unit>> it = m.entrySet().iterator();
        while (it.hasNext())
        {
            Map.Entry<Integer, Unit> e = it.next();
            int k = e.getKey();
            Unit u = e.getValue();
            System.out.println(k + ":" + u.s);
        }

        System.out.println(split);

        HashMap<Integer, String> hm = new HashMap<Integer, String>();
        hm.put(1, "x");
        hm.put(1, "a");
        hm.put(2, "b");
        hm.put(3, "c");
        System.out.println(hm.toString());
        Iterator<Integer> hm_it = hm.keySet().iterator();
        while (hm_it.hasNext())
        {
            Integer k = hm_it.next();
            if (k == 2)
            {
                it.remove();
            }
        }
        System.out.println(hm.toString());

        System.out.println(split);

        Object[] keys = hm.keySet().toArray();
        for (Object k : keys)
        {
            Integer i = (Integer) k;
            System.out.println(i);
        }

        System.out.println(split);

        Integer[] ks = hm.keySet().toArray(new Integer[0]);
        for (Integer k : ks)
        {
            System.out.println(k);
        }
        String[] vs = hm.values().toArray(new String[0]);
        for (String v : vs)
        {
            System.out.println(v);
        }

        System.out.println(split);

        class Status
        {
            String create_time;
            long id;
        }
        Status status;
        Map<String, Status> statuses = new HashMap<>();
        status = new Status();
        status.create_time = "2014-10-01";
        status.id = 4;
        statuses.put(status.create_time, status);
        status = new Status();
        status.create_time = "2013-10-01";
        status.id = 5;
        statuses.put(status.create_time, status);
        status = new Status();
        status.create_time = "2015-05-01";
        status.id = 1;
        statuses.put(status.create_time, status);
        status = new Status();
        status.create_time = "2015-03-01";
        status.id = 2;
        statuses.put(status.create_time, status);
        status = new Status();
        status.create_time = "2015-10-01";
        status.id = 3;
        statuses.put(status.create_time, status);

        System.out.println("原始记录");
        for (Map.Entry<String, Status> entry : statuses.entrySet())
        {
            status = entry.getValue();
            System.out.println(
                    String.format("%s %d", status.create_time, status.id));
        }

        System.out.println("按键排序");
        Object[] times = statuses.keySet().toArray();
        Arrays.sort(times);
        for (Object k : times)
        {
            status = statuses.get(k);
            System.out.println(String.format("%s %d", k, status.id));
        }

        System.out.println("保留最新的3条");
        for (int i = 0; i < times.length - 3; i++)
        {
            statuses.remove(times[i]);
        }
        for (Map.Entry<String, Status> entry : statuses.entrySet())
        {
            status = entry.getValue();
            System.out.println(
                    String.format("%s %d", status.create_time, status.id));
        }

        System.out.println(split);

        System.out.println("TreeMap键按序遍历");

        SortedMap<Integer, String> sorted_map = new TreeMap<>();
        sorted_map.put(28, "华为");
        sorted_map.put(26, "中兴");
        sorted_map.put(22, "小米");
        sorted_map.put(13, "魅族");
        sorted_map.put(250, "锤子");
        sorted_map.forEach((k, v) -> {
            System.out.println(k + " -> " + v);
        });
    }

    private void cls()
    {
        class F
        {
            void func()
            {
                System.out.println("func");
            }
        }
        new F().func();

        class Base
        {
            Base()
            {
                System.out.println("Base");
            }

            Base(String s)
            {
                System.out.println("Base " + s);
            }
        }
        class Sub extends Base
        {
            Sub()
            {
                System.out.println("Sub");
            }

            Sub(String s)
            {
                super(s); // 不用super(s)的话，调用基类缺省构造方法Base()
                System.out.println("Sub " + s);
            }
        }
        new Sub();
        new Sub("ok");
    }

    private void random()
    {
        System.out.println("random()");
        String split = "------------------------------";
        System.out.println(split);

        Random rand = new Random();
        System.out.println("[0,1): " + rand.nextInt(1));

        int limit = rand.nextInt(10) + 2;
        System.out.print(String.format("limit(%d): ", limit));
        for (int i = 0; i < limit; i++)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        for (int i = 0; i < rand.nextInt(10) + 2; i++)
        {
            System.out.print(i + " ");
        }
        System.out.println();
    }

    private void uuid() throws Exception
    {
        UUID uuid = UUID.randomUUID();
        System.out.println(uuid.toString());
        System.out.println(uuid.toString().toUpperCase());
        for (int i = 0; i < 5; i++)
        {
            System.out.println(UUID.randomUUID().toString().replaceAll("-", "")
                    .toLowerCase());
        }
    }

    private void operator()
    {
        byte b = 0;
        for (int i = 0; i < 7; ++i)
        {
            b |= (0x80 >> i);
        }
        System.out.println(String.format("%X", b));
        System.out.println();

        int n = 0;
        byte[] arr = { (byte) 0x82, 0x34, 0x56, 0x78 };
        for (byte a : arr)
        {
            n <<= 8;
            n |= a;
        }
        System.out.println(String.format("n: %X", n));
        System.out.println();

        byte p = (byte) 0x80;
        boolean is_set = ((p & 0x80) != 0);
        if (is_set)
        {
            System.out.println(String.format("0x%X is set", p));
        }
        System.out.println();

        int size = 0x82345678;
        byte[] size_arr = new byte[4];
        int size_tmp = size;
        for (int i = 0; i < size_arr.length; ++i)
        {
            size_arr[size_arr.length - i - 1] = (byte) (size_tmp & 0xff);
            size_tmp >>= 8;
        }
        System.out.println(String.format("%d 0x%X", size, size));
        for (byte s : size_arr)
        {
            System.out.println(String.format("0x%X", s));
        }
    }

    private void string() throws Exception
    {
        String split = "----------------------------------------";

        String s = null;
        System.out.println("(" + s + ")");

        s = new String(new byte[0]);
        System.out.println("(" + s + ")");
        byte[] buf = new byte[10];
        s = new String(buf, 5, 0);
        System.out.println("(" + s + ")");

        System.out.println(100 + 200 + " hello");

        s = "  {\"name\":\"小明\"}";
        System.out.println(s);
        int idx = s.indexOf("{");
        s = s.substring(0, idx + 1) + "\"svc\":\"getUser\","
                + s.substring(idx + 1);
        System.out.println(s);

        System.out.println(split);

        s = "你得到的优惠券：%%，请使用";
        String r = s.replaceFirst("%%", "ABCDEFGH");
        System.out.println(String.format("orig(%s) new(%s)", s, r));

        System.out.println(split);

        String fmt = "你还剩下%2$d天，%1$d小时";
        System.out.println(String.format(fmt, 100, 20));

        System.out.println(split);

        s = "春满人间世，日照大旗红。携卷登高唱，流韵壮东风";
        System.out.println(
                String.format("string(UTF-8):%s length:%d", s, s.length()));
        byte[] b = s.getBytes("UTF-8");
        if (isUTF8(b))
        {
            System.out.println("is utf-8");
        }
        System.out.println(String.format("array(UTF-8): %d", b.length));
        b = s.getBytes("GB18030");
        System.out.println(String.format("array(GB18030): %d", b.length));

        String s2 = new String(b, "GB18030");
        System.out.println(
                String.format("string(GB18030):%s length:%d", s2, s2.length()));
        byte[] b2 = s2.getBytes("UTF-8");
        System.out.println(String.format("array(UTF-8): %d", b2.length));

        byte[] b_gb = "壮东风abc_+-|/第一".getBytes("GB18030");
        for (int i = 0; i < b_gb.length; ++i)
        {
            System.out.print(String.format("%02X ", b_gb[i]));
        }
        System.out.println();
        if (isUTF8(b_gb))
        {
            System.out.println("b_gb is utf-8");
        }
        String s_gb = new String(b_gb, "GB18030");
        System.out.println(
                String.format("string(GB18030): %s %d", s_gb, s_gb.length()));
        byte[] b_u = s_gb.getBytes("UTF-8");
        for (int i = 0; i < b_u.length; ++i)
        {
            System.out.print(String.format("%02X ", b_u[i]));
        }
        System.out.println();
        if (s_gb.matches(".*[`!@#$%^&*\\\\|'\"].*"))
        {
            System.out.println("s_gb is invalid");
        }

        System.out.println(split);

        s = "春满人间世，日照大旗红。携卷登高唱，流韵壮东风";
        String s_gbk = new String(s.getBytes("UTF-8"), "GBK");
        System.out.println(String.format("误转GBK：%s", s_gbk));
        String s_utf8 = new String(s_gbk.getBytes("GBK"), "UTF-8");
        System.out.println(String.format("还原UTF-8：%s", s_utf8));

        System.out.println(split);

        s = "Hello World HeLLO WORLD";
        System.out.println(s);
        s.toLowerCase();
        System.out.println(s);

        String l = s.toLowerCase();
        String filter = "hello";
        String filter_replace = new String();
        for (int i = 0; i < filter.length(); ++i)
            filter_replace += "*";
        int offset = 0;
        while ((offset = l.indexOf(filter, offset)) != -1)
        {
            s = s.substring(0, offset) + filter_replace
                    + s.substring(offset + filter.length());
            offset += filter.length();
            System.out.println(s);
        }
        System.out.println(s);

        l = s.toLowerCase();
        filter = "or";
        filter_replace = new String();
        for (int i = 0; i < filter.length(); ++i)
            filter_replace += "+";
        offset = 0;
        while ((offset = l.indexOf(filter, offset)) != -1)
        {
            s = s.substring(0, offset) + filter_replace
                    + s.substring(offset + filter.length());
            offset += filter.length();
            System.out.println(s);
        }
        System.out.println(s);

        System.out.println(split);

        s = "����";
        for (byte by : s.getBytes())
        {
            System.out.print(String.format("%02X ", by));
        }
        System.out.println();
        char replacement = new String(
                new byte[] { (byte) 0xEF, (byte) 0xBF, (byte) 0xBD })
                        .toCharArray()[0];
        System.out.println(String.format("replacement: %c ", replacement));
        for (char ch : s.toCharArray())
        {
            if (ch == replacement)
                System.out.print(String.format("%c ", ch));
        }
        System.out.println();
    }

    private void integer()
    {
        System.out.println("integer()");
        String split = "------------------------------";
        System.out.println(split);

        int i = 9999; // 9999 mod 0xFF = 15

        System.out.println("等价");
        System.out.println(
                "String Integer.toString(int): " + Integer.toString(i));
        System.out.println("String String.valueOf(int): " + String.valueOf(i));
        System.out.println();
        System.out.println(
                "String Integer.toHexString(int): " + Integer.toHexString(i));

        System.out.println();

        System.out
                .println("Integer Integer.valueOf(int): " + Integer.valueOf(i));
        System.out.println("等价");
        String s = Integer.toString(i);
        System.out.println(
                "Integer Integer.valueOf(String): " + Integer.valueOf(s));
        System.out.println(
                "Integer Integer.parseInt(String): " + Integer.parseInt(s));

        System.out.println();

        System.out.println(
                "Integer.byteValue(int): " + Integer.valueOf(i).byteValue());
        byte[] b = Integer.toString(i).getBytes();
        s = new String(b);
        int i2 = Integer.valueOf(s);
        System.out.println("int -> String -> byte[] -> String -> int: " + i2);
    }

    private boolean is_utf8(char ch)
    {
        return 0x4e00 <= ch && ch <= 0x9fa5;
    }

    private boolean isUTF8(byte[] arr)
    {
        int byte_count = 0; // UFT8可用1-6个字节编码,ASCII用一个字节
        for (int i = 0; i < arr.length; ++i)
        {
            int b = (int) (arr[i] & 0xff);
            // System.out.println(b);
            if (byte_count == 0) // 首字符
            {
                if (b >= 0x80)
                {
                    if (0xFC <= b && b <= 0xFD) // 1111110x 10xxxxxx 10xxxxxx
                                                // 10xxxxxx 10xxxxxx 10xxxxxx
                        byte_count = 6;
                    else if (0xF8 <= b) // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
                                        // 10xxxxxx
                        byte_count = 5;
                    else if (0xF0 <= b) // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                        byte_count = 4;
                    else if (0xE0 <= b) // 1110xxxx 10xxxxxx 10xxxxxx
                        byte_count = 3;
                    else if (0xC0 <= b) // 110xxxxx 10xxxxxx
                        byte_count = 2;
                    else
                        return false;
                    --byte_count;
                }
            }
            else
            // 非首字节：0x80(10000000) - 0xBF(10111111)
            {
                if ((b & 0xC0) != 0x80)
                    return false;
                --byte_count;
            }
        }
        if (byte_count > 0)
            return false;
        return true;
    }

    private void charset() throws Exception
    {
        String split = "----------------------------------------";

        String utf8 = "中文";
        byte[] barray = utf8.getBytes();
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();
        String gb18030 = new String(utf8.getBytes("UTF-8"), "GB18030");
        String gb2312 = new String(utf8.getBytes("UTF-8"), "GB2312");
        String iso88591 = new String(utf8.getBytes("UTF-8"), "ISO-8859-1");

        System.out.println(utf8);
        System.out.println(utf8.getBytes());
        System.out.println(utf8.getBytes("GB2312"));
        System.out.println(utf8.getBytes("ISO-8859-1"));

        System.out.println("UTF-8 --> UTF8: " + new String(utf8.getBytes()));
        System.out.println(
                "UTF-8 --> GB2312: " + new String(utf8.getBytes(), "GB2312"));
        System.out.println("UTF-8 --> ISO-8859-1: "
                + new String(utf8.getBytes(), "ISO-8859-1"));

        System.out.println(
                "GB2312 --> UTF-8: " + new String(utf8.getBytes("GB2312")));

        System.out.println("GB2312 --> GB2312: "
                + new String(utf8.getBytes("GB2312"), "GB2312"));

        System.out.println("GB2312 --> ISO-8859-1: "
                + new String(utf8.getBytes("GB2312"), "ISO-8859-1"));
        System.out.println("ISO-8859-1 --> UTF-8 : "
                + new String(utf8.getBytes("ISO-8859-1")));
        System.out.println("ISO-8859-1 --> GB2312: "
                + new String(utf8.getBytes("ISO-8859-1"), "GB2312"));

        System.out.println("ISO-8859-1 --> ISO-8859-1: "
                + new String(utf8.getBytes("ISO-8859-1"), "ISO-8859-1"));

        System.out.println(split);

        String utf8_new;

        System.out.println("UTF-8 --> GB18030 --> UTF-8    OK");
        System.out.println(gb18030);
        utf8_new = new String(gb18030.getBytes("GB18030"), "UTF-8");
        System.out.println(utf8_new);
        barray = utf8.getBytes("GB18030");
        String gb18030_2 = new String(barray, "GB18030");
        System.out.println(gb18030_2);
        System.out.println();

        System.out.println("UTF-8 --> ISO-8859-1 bytes, wrong");
        barray = utf8.getBytes("ISO-8859-1");
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();

        System.out.println("GB18030 --> ISO-8859-1 bytes, wrong");
        barray = gb18030.getBytes("ISO-8859-1");
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();

        System.out.println("GB2312 --> ISO-8859-1 bytes, wrong");
        barray = gb2312.getBytes("ISO-8859-1");
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();

        System.out.println("ISO-8859-1 encode to String");
        System.out.println(iso88591);
        barray = iso88591.getBytes("ISO-8859-1");
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();

        System.out.println("ISO-8859-1 bytes");
        barray = iso88591.getBytes("ISO-8859-1");
        for (byte b : barray)
        {
            System.out.print(String.format("%02X ", b));
        }
        System.out.println();

        if (isUTF8(iso88591.getBytes("ISO-8859-1")))
        {
            System.out.println(
                    String.format("%s is ISO-8859-1(UTF-8)", iso88591));
        }
        else
        {
            System.out.println(
                    String.format("%s is not ISO-8859-1(UTF-8)", iso88591));
        }

        if (isUTF8(utf8.getBytes("ISO-8859-1")))
        {
            System.out.println(String.format("%s is ISO-8859-1(UTF-8)", utf8));
        }
        else
        {
            System.out.println(
                    String.format("%s is not ISO-8859-1(UTF-8)", utf8));
        }
        System.out.println();

        System.out.println("UTF-8 --> ISO-8859-1 --> UTF-8 OK");
        utf8_new = new String(iso88591.getBytes("ISO-8859-1"), "UTF-8");
        System.out.println(utf8_new);
        System.out.println();

        System.out.println("UTF-8 --> GB2312 --> UTF-8    NO");
        System.out.println(gb2312);
        utf8_new = new String(gb2312.getBytes("GB2312"), "UTF-8");
        System.out.println(utf8_new);

        System.out.println(split);

        System.out.println("不可靠判断");
        System.out.println();

        System.out.println(gb2312);
        String gb2312_new = new String(gb2312.getBytes("GB2312"), "GB2312");
        System.out.println(gb2312_new);
        if (gb2312.equals(new String(gb2312.getBytes("GB2312"), "GB2312")))
        {
            System.out.println("gb2312 is GB2312");
        }
        if (gb2312.equals(new String(gb2312.getBytes("UTF-8"), "UTF-8")))
        {
            System.out.println("gb2312 is UTF-8");
        }
        System.out.println();

        System.out.println(iso88591);
        String iso88591_new = new String(iso88591.getBytes("ISO-8859-1"),
                "ISO-8859-1");
        System.out.println(iso88591_new);
        if (iso88591.equals(
                new String(iso88591.getBytes("ISO-8859-1"), "ISO-8859-1")))
        {
            System.out.println("iso88591 is ISO-8859-1");
        }
        if (iso88591.equals(new String(iso88591.getBytes("UTF-8"), "UTF-8")))
        {
            System.out.println("iso88591 is UTF-8");
        }

        System.out.println(split);

        System.out.println("将拉丁字母转化为相近英文字母");
        System.out.println();

        String latin = "café Rodríguez González Teódulo Jesús";
        String ascii = Util.convertLatin(latin);
        System.out.println(String.format("%s -> %s", latin, ascii));
    }

    private void singleton()
    {
        Singleton a = Singleton.getInstance("a");
        a.hello();
        Singleton b = Singleton.getInstance("b");
        b.hello();
        Singleton def = Singleton.getInstance();
        def.hello();
    }

    private void static_member()
    {
        System.out.println(new StaticMember().get(1));
        System.out.println(new StaticMember().get(3));

        String text = "上海";
        System.out.println(text + ": " + WeatherArea.getCode(text));
    }

    private void varargs()
    {
        List<String> args = new ArrayList<>();
        args.add("hello");
        args.add("world");
        args.add("你好");
        _varargs_call(args.stream().map(String::getBytes)
                .collect(Collectors.toList()).toArray(new byte[0][]));
    }

    private void _varargs_call(byte[]... args)
    {
        for (byte[] arg : args)
        {
            System.out.println(new String(arg));
        }
    }
}

class Util
{
    public static String convertLatin(String orig)
    {
        StringBuilder conv = new StringBuilder();
        for (char c : orig.toCharArray())
        {
            char r = c;
            switch (c)
            {
            case 'á':
                r = 'a';
                break;
            case 'é':
                r = 'e';
                break;
            case 'í':
                r = 'i';
                break;
            case 'ó':
                r = 'o';
                break;
            case 'ú':
                r = 'u';
                break;
            }
            conv.append(r);
        }
        return conv.toString();
    }
}

class Singleton
{
    private static Singleton inst_a = new Singleton("a");
    private static Singleton inst_b = new Singleton("b");
    private static Singleton inst = new Singleton();

    private Singleton()
    {
        this.name = "default";
    }

    private Singleton(String name)
    {
        this.name = name;
    }

    public static Singleton getInstance()
    {
        return inst;
    }

    public static Singleton getInstance(String name)
    {
        switch (name)
        {
        case "a":
            return inst_a;
        case "b":
            return inst_b;
        default:
            return inst;
        }
    }

    private String name;

    public void hello()
    {
        System.out.println("hello " + this.name);
    }
}

class StaticMember
{
    // 类加载的时候执行，线程安全
    static
    {
        HashMap<Integer, String> m = new HashMap<Integer, String>();
        m.put(1, "hello");
        m.put(2, "world");
        StaticMember.map = m;
        System.out.println("StaticMember init");
    }

    private static HashMap<Integer, String> map;

    // 外部调用方法，触发static块
    public String get(int k)
    {
        return map.get(k);
    }
}
